using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
using Mono.Cecil;
using static UnityEngine.RuleTile.TilingRuleOutput;

public static class Util
{
    /// <summary>
    /// 常规四方向
    /// </summary>
    public enum CardinalDirection
    {
        Top,
        Bottom,
        Left,
        Right,
    }
    /// <summary>
    /// 对角线方向
    /// </summary>
    public enum DiagonalDirection
    {
        LeftTop,
        LeftBottom,
        RightTop,
        RightBottom,
    }
    /// <summary>
    /// 得到鼠标世界坐标（z为0）
    /// </summary>
    /// <returns></returns>
    public static Vector3 GetMouseWorldPosition()
    {
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        return new Vector3(mousePos.x, mousePos.y, 0);
    }

    /// <summary>
    /// 得到前后左右 输入的V2
    /// </summary>
    /// <returns>vector2</returns>
    public static Vector2 GetValue2_HorizontalAndVertical()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector2 hv = new Vector2(h, v);
        return hv.magnitude > 1 ? hv.normalized : hv;
    }
    /// <summary>
    /// 得到前后左右 输入的V3
    /// </summary>
    /// <returns>vector3</returns>
    public static Vector3 GetValue3_HorizontalAndVertical()
    {
        float h = Input.GetAxis("Horizontal");
        float v = Input.GetAxis("Vertical");
        Vector3 hv = new Vector3(h, v, 0);
        return hv.magnitude > 1 ? hv.normalized : hv;
    }
    /// <summary>
    /// 从l中随机选取count个数据(不放回)
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="l"></param>
    /// <param name="count"></param>
    /// <returns></returns>
    public static List<T> RandomGetValue<T>(IEnumerable<T> l, int count)
    {
        List<T> list = new List<T>();
        List<T> resList = new List<T>();
        foreach (var item in l)
        {
            list.Add(item);
        }
        int listCount = list.Count;
        for (int i = 0; i < Mathf.Min(count, listCount); i++)
        {
            int randomIndex = UnityEngine.Random.Range(0, list.Count - 1);
            resList.Add(list[randomIndex]);
            list.RemoveAt(randomIndex);
        }
        return resList;
    }
    /// <summary>
    /// 得到平面上两点的曼哈顿距离
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static float GetManhattanDistance(Vector2 a, Vector2 b)
    {
        return Mathf.Abs(a.x - b.x) + Mathf.Abs(a.y - b.y);
    }
    /// <summary>
    /// 得到平面上两点的欧氏距离
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <returns></returns>
    public static float GetEuclideanDistance(Vector2 a, Vector2 b)
    {
        return Mathf.Pow(Mathf.Pow(a.x - b.x, 2) + Mathf.Pow(a.y - b.y, 2), 0.5f);
    }
    /// <summary>
    /// 根据可能性随机返回数组元素
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="t">待返回元素数组</param>
    /// <param name="probabilitys">元素可能性数组</param>
    /// <returns></returns>
    public static T GetRandomTByProbability<T>(List<T> t, List<int> probabilitys) where T : class
    {
        int totalP = probabilitys.Sum();
        int random = UnityEngine.Random.Range(1, totalP + 1);
        int curProbability = 0;
        for (int i = 0; i < probabilitys.Count; i++)
        {
            if (probabilitys[i] == 0)
            {
                continue;
            }
            curProbability += probabilitys[i];
            if (i != probabilitys.Count - 1)
            {
                if (random >= curProbability && random < curProbability + probabilitys[i + 1])
                {
                    return t[i];
                }

            }
            else
            {
                return t.Last();
            }
        }
        return null;
    }
    /// <summary>
    /// 得到精灵图的Pivot位置和未缩放大小
    /// </summary>
    /// <param name="tran"></param>
    /// <param name="spriteRender"></param>
    /// <returns></returns>
    public static (Vector2, Vector2) GetPivotAndSize(SpriteRenderer spriteRender)
    {
        float pixelsPerUnit = spriteRender.sprite.pixelsPerUnit;
        Vector2 size = (spriteRender.sprite.rect.size / pixelsPerUnit);
        Vector2 customPivot = spriteRender.sprite.pivot / pixelsPerUnit / size;
        return (customPivot, size);
    }
    /// <summary>
    /// 得到精灵图的Pivot位置和缩放大小
    /// </summary>
    /// <param name="tran"></param>
    /// <param name="spriteRender"></param>
    /// <returns></returns>
    public static (Vector2, Vector2) GetPivotAndSize(SpriteRenderer spriteRender, Vector3 localScale)
    {
        float pixelsPerUnit = spriteRender.sprite.pixelsPerUnit;
        Vector2 size = (spriteRender.sprite.rect.size / pixelsPerUnit);
        Vector2 customPivot = spriteRender.sprite.pivot / pixelsPerUnit / size;
        size *= localScale;
        return (customPivot, size);
    }

    /// <summary>
    /// dijkstra求单源最短路径
    /// </summary>
    /// /// <param name="map"></param>
    /// <param name="st"></param>
    public static List<List<float>> dijkstra(List<List<float>> map, int st)
    {
        var mapRes = new List<List<float>>();
        for (int i = 0; i < map.Count; i++)
        {
            mapRes.Add(new List<float>());
            for (int j = 0; j < map[i].Count; j++)
            {
                mapRes[i].Add(map[i][j]);
            }
        }
        List<bool> flagList = new List<bool>();
        for (int i = 0; i < mapRes.Count; i++)
        {
            flagList.Add(false);
        }
        for (int i = 0; i < mapRes.Count; i++)
        {
            //找到和起点距离最短的点
            float minx = float.PositiveInfinity;
            int minIndex = 0;
            for (int j = 0; j < mapRes.Count; j++)
            {
                if (flagList[j] == false && mapRes[st][j] <= minx)
                {
                    minx = mapRes[st][j];
                    minIndex = j;
                }
            }
            //并标记
            flagList[minIndex] = true;
            //更新所有和它连接的点的距离
            for (int j = 0; j < mapRes.Count; j++)
            {
                if (flagList[j] == false && mapRes[st][j] > mapRes[st][minIndex] + mapRes[minIndex][j])
                    mapRes[st][j] = mapRes[st][minIndex] + mapRes[minIndex][j];
            }
        }
        return mapRes;
    }
    /// <summary>
    /// 随机得到当前点上下左右随机一个点
    /// </summary>
    /// <param name="pos"></param>
    /// <returns></returns>
    public static Vector2Int GetRandomPointFromFourDirecton(Vector2Int pos)
    {
        int randomValue = UnityEngine.Random.Range(0, 4);
        switch (randomValue)
        {
            case 0:
                return pos + EightDirections.Top;
            case 1:
                return pos + EightDirections.Bottom;
            case 2:
                return pos + EightDirections.Left;
            case 3:
                return pos + EightDirections.Right;
            default:
                return pos;
        }
    }
    /// <summary>
    /// 判断一个点是不是在给定的矩形范围内，不包含右、上边界
    /// </summary>
    /// <param name="pos">当前点</param>
    /// <param name="minPoint">左下角点</param>
    /// <param name="maxPoint">右上角点</param>
    /// <returns></returns>
    public static bool InRectArea(Vector2Int pos, Vector2Int minPoint, Vector2Int maxPoint)
    {
        if (pos.x >= minPoint.x && pos.x < maxPoint.x && pos.y >= minPoint.y && pos.y < maxPoint.y)
        {
            return true;
        }
        return false;
    }
    /// <summary>
    /// 判断一个点是不是在给定的矩形范围内，不包含右、上边界
    /// </summary>
    /// <param name="pos">当前点</param>
    /// <param name="minPoint">左下角点</param>
    /// <param name="maxPoint">右上角点</param>
    /// <returns></returns>
    public static bool InRectArea(Vector2 pos, Vector2 minPoint, Vector2 maxPoint)
    {
        if (pos.x >= minPoint.x && pos.x < maxPoint.x && pos.y >= minPoint.y && pos.y < maxPoint.y)
        {
            return true;
        }
        return false;
    }
    /// <summary>
    /// 得到num转为二进制后 0和1的数量
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    public static (int zeroCount, int oneCount) GetBinaryCharCount(int num)
    {
        int zeroCount = 0;
        int oneCount = 0;
        if (num == 0)
        {
            zeroCount++;
        }
        while (num != 0)
        {
            if ((num & 1) == 1)
            {
                oneCount++;
            }
            else
            {
                zeroCount++;
            }
            num >>= 1;
        }
        return (zeroCount, oneCount);
    }
    /// <summary>
    /// 得到贝塞尔曲线上t处点的坐标
    /// </summary>
    /// <param name="t">0到1的值，0获取曲线的起点，1获得曲线的终点</param>
    /// <param name="start">曲线的起始位置</param>
    /// <param name="center">决定曲线形状的控制点</param>
    /// <param name="end">曲线的终点</param>
    /// <returns></returns>
    public static Vector3 GetBezierPoint(float t, Vector3 start, Vector3 center, Vector3 end)
    {
        return (1 - t) * (1 - t) * start + 2 * t * (1 - t) * center + t * t * end;
    }
    /// <summary>
    /// 判断value是否在指定范围内，[min,max]
    /// </summary>
    /// <param name="value"></param>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public static bool InRange(int value,int min,int max)
    {
        return value >= min && value <= max;
    }
    /// <summary>
    /// 判断value是否在指定范围内，[min,max]
    /// </summary>
    /// <param name="value"></param>
    /// <param name="range"></param>
    /// <returns></returns>
    public static bool InRange(int value, Vector2 range)
    {
        return value >= range.x && value <= range.y;
    }
    /// <summary>
    /// 八方向的变化量
    /// </summary>
    public static class EightDirections
    {
        public static Vector2Int Top = new Vector2Int(0, 1);
        public static Vector2Int Bottom = new Vector2Int(0, -1);
        public static Vector2Int Left = new Vector2Int(-1, 0);
        public static Vector2Int Right = new Vector2Int(1, 0);
        public static Vector2Int LeftTop = new Vector2Int(-1, 1);
        public static Vector2Int LeftBottom = new Vector2Int(-1, -1);
        public static Vector2Int RightTop = new Vector2Int(1, 1);
        public static Vector2Int RightBotton = new Vector2Int(1, -1);
    }
}
